package client;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.util.Scanner;
import java.io.PrintWriter;

public class Client implements Runnable {
	private String hostname;
	private int port;
	Socket socketClient;
	protected BufferedReader bufferReader;
	protected BufferedWriter bufferWriter;
	PrintWriter out;
	String userInput;
	static String nick = null;
	Scanner in;
	String response = null;
	// informacje o graczu
	int id;
	int playersBalance;
	int playersBet;
	boolean canBet;
	boolean canExchange;

	// informacje o stole
	int maxBet;
	int pot;

	// GUI
	ClientGUI cg;
	// For bot
	BotPlayer bp;

	// Constructor for HumanPlayer, our original constructor :)
	Client(String hostname, int port, ClientGUI cg) {
		this.hostname = hostname;
		this.port = port;
		this.cg = cg;

		// this.end = false;
	}

	public Client(String host, int port, BotPlayer bp) {
		this.hostname = host;
		this.port = port;
		this.bp = bp;
	}

	public void run() {
		try {
			creatingcommunication();
			while (true) {
				parseAction(splitCommand(receive()));
			}
		} catch (IOException e) {
		}
	}

	public String[] splitCommand(String command) {
		System.out.println(command);
		String[] s = command.split(" ");
		return s;
	}

	public void parseAction(String[] command) throws IOException {
		switch (command[2]) {
		case "playerinfo":
			// set player's variables
			playersBalance = Integer.parseInt(command[4]);
			playersBet = Integer.parseInt(command[5]);
			id = Integer.parseInt(command[3]);
			// set text to labels
			cg.setCashLbl("balance", playersBalance);
			cg.setCashLbl("bet", playersBet);
			// enable raise/bet textfield
			cg.setTfRaiseEnabled(true);
			// enable start button if player has ID = 0
			if (id == 0) {
				cg.enableStartButton(true);
			}
			// fill opponentpannels with ids
			for (int i = 0; i < 5; i++) {
				cg.op[i].id = (id + i + 1) % 6;
				cg.op[i].setLabelID(cg.op[i].id);
			}
			break;
		case "permission":
			if (command[3].equals("1"))
				cg.setButtonEnabled("bet", true);
			else
				cg.setButtonEnabled("bet", false);

			if (command[4].equals("1"))
				cg.setButtonEnabled("raise", true);
			else
				cg.setButtonEnabled("raise", false);

			if (command[5].equals("1"))
				cg.setButtonEnabled("check", true);
			else
				cg.setButtonEnabled("check", false);

			if (command[6].equals("1"))
				cg.setButtonEnabled("call", true);
			else
				cg.setButtonEnabled("call", false);

			if (command[7].equals("1"))
				cg.setButtonEnabled("allin", true);
			else
				cg.setButtonEnabled("allin", false);

			if (command[8].equals("1"))
				cg.setButtonEnabled("fold", true);
			else
				cg.setButtonEnabled("fold", false);

			if (command[9].equals("1"))
				cg.setButtonEnabled("exchange", true);
			else
				cg.setButtonEnabled("exchange", false);
			break;
		case "opponentinfo":
			int o = Integer.parseInt(command[3]);
			for (int i = 0; i < cg.op.length; i++) {
				if (o == cg.op[i].id) {
					cg.op[i].setLabelNick(command[1]);
					cg.op[i].updateLabels(Integer.parseInt(command[5]),
							Integer.parseInt(command[4]));
				}
			}
			break;
		case "newplayer":
			cg.setStBar("New player: " + command[1]);
			int p = Integer.parseInt(command[3]);
			for (int i = 0; i < cg.op.length; i++) {
				if (p == cg.op[i].id) {
					cg.op[i].setLabelNick(command[1]);
					cg.op[i].updateLabels(Integer.parseInt(command[5]),
							Integer.parseInt(command[4]));
				}
			}
			break;
		case "disconnect":
			cg.setStBar(command[1] + " disconnected from server");
			int q = Integer.parseInt(command[3]);
			for (int i = 0; i < cg.op.length; i++) {
				if (q == cg.op[i].id) {
					cg.op[i].resetPanel();
				}
			}
			break;
		case "start":
			switch (command[3]) {
			case "ok":
				cg.enableStartButton(false);
				cg.setStBar("Game started");
				break;
			case "err":
				cg.setStBar("Not enough players!");
				break;
			}
			break;

		case "cards":
			for (int i = 0; i < 4; i++)
				cg.setCards(i, command[i + 3]);
			break;
		case "bet":
			// update status bar
			cg.setStBar(command[1] + ": bet " + command[3]);
			// update pot and max bet
			pot = Integer.parseInt(command[5]);
			maxBet = Integer.parseInt(command[6]);
			cg.setCashLbl("pot", pot);
			cg.setCashLbl("maxbet", maxBet);
			// if performed by player
			if (Integer.parseInt(command[0]) == id) {
				playersBet = Integer.parseInt(command[3]);
				playersBalance = Integer.parseInt(command[4]);
				cg.setCashLbl("balance", playersBalance);
				cg.setCashLbl("bet", playersBet);
			}
			// if performed by opponent
			else {
				// get panel ID
				int oppid = 0;
				for (int i = 0; i < cg.op.length; i++) {
					if (Integer.parseInt(command[0]) == cg.op[i].id)
						oppid = i;
				}
				// update panel
				cg.op[oppid].updateLabels(Integer.parseInt(command[3]),
						Integer.parseInt(command[4]));
			}
			break;

		case "raise":
			// update status bar
			cg.setStBar(command[1] + ": raise " + command[3]);
			// update pot and max bet
			pot = Integer.parseInt(command[5]);
			maxBet = Integer.parseInt(command[6]);
			cg.setCashLbl("pot", pot);
			cg.setCashLbl("maxbet", maxBet);
			// if performed by player
			if (Integer.parseInt(command[0]) == id) {
				playersBet = Integer.parseInt(command[3]);
				playersBalance = Integer.parseInt(command[4]);
				cg.setCashLbl("balance", playersBalance);
				cg.setCashLbl("bet", playersBet);
			}
			// if performed by opponent
			else {
				// get panel ID
				int oppid = 0;
				for (int i = 0; i < cg.op.length; i++) {
					if (Integer.parseInt(command[0]) == cg.op[i].id)
						oppid = i;
				}
				// update panel
				cg.op[oppid].updateLabels(Integer.parseInt(command[3]),
						Integer.parseInt(command[4]));
			}
			break;

		case "check":
			cg.setStBar(command[1] + ": check ");
			break;
		case "call":
			// update status bar
			cg.setStBar(command[1] + ": call ");
			// update pot and max bet
			pot = Integer.parseInt(command[5]);
			maxBet = Integer.parseInt(command[6]);
			cg.setCashLbl("pot", pot);
			cg.setCashLbl("maxbet", maxBet);
			// if performed by player
			if (Integer.parseInt(command[0]) == id) {
				playersBet = Integer.parseInt(command[3]);
				playersBalance = Integer.parseInt(command[4]);
				cg.setCashLbl("balance", playersBalance);
				cg.setCashLbl("bet", playersBet);
			}
			// if performed by opponent
			else {
				// get panel ID
				int oppid = 0;
				for (int i = 0; i < cg.op.length; i++) {
					if (Integer.parseInt(command[0]) == cg.op[i].id)
						oppid = i;
				}
				// update panel
				cg.op[oppid].updateLabels(Integer.parseInt(command[3]),
						Integer.parseInt(command[4]));
			}
			break;
		case "allin":
			// update status bar
			cg.setStBar(command[1] + ": all-in ");
			// update pot and max bet
			pot = Integer.parseInt(command[5]);
			maxBet = Integer.parseInt(command[6]);
			cg.setCashLbl("pot", pot);
			cg.setCashLbl("maxbet", maxBet);
			// if performed by player
			if (Integer.parseInt(command[0]) == id) {
				playersBet = Integer.parseInt(command[3]);
				playersBalance = Integer.parseInt(command[4]);
				cg.setCashLbl("balance", playersBalance);
				cg.setCashLbl("bet", playersBet);
			}

			// if performed by opponent
			else {
				// get panel ID
				int oppid = 0;
				for (int i = 0; i < cg.op.length; i++) {
					if (Integer.parseInt(command[0]) == cg.op[i].id)
						oppid = i;
				}
				// update panel
				cg.op[oppid].updateLabels(Integer.parseInt(command[3]),
						Integer.parseInt(command[4]));
			}
			break;

		case "winner":
			// update status bar
			cg.setStBar("WINNER: " + command[1] + "!");
			// reset bet, maxbet, pot
			cg.resetBets();
			// hide client's cards
			cg.resetCards();

			// if player won
			if (Integer.parseInt(command[0]) == id) {
				playersBalance = Integer.parseInt(command[3]);
				cg.setCashLbl("balance", playersBalance);
			}
			// if opponent won
			else {
				// get winner's panel ID
				int oppid = -1;
				for (int i = 0; i < cg.op.length; i++) {
					if (Integer.parseInt(command[0]) == cg.op[i].id)
						oppid = i;
				}
				// update panel
				cg.op[oppid].updateLabels(0, Integer.parseInt(command[3]));
			}
			break;

		case "beterr":
			cg.setStBar("You cannot do this!");
			break;

		case "fold":
			cg.setStBar(command[1] + ": fold ");
			break;
		case "exchange":
			cg.setStBar(command[1] + ": exchange " + command[3] + " cards");
			break;
		}
	}

	public void connect() throws IOException, Exception // run()
	{
		System.out
				.println("Connecting to the server: " + hostname + ":" + port);
		try {
			if (port > 65535 || port < 0) {
				throw new Exception("Invalid port");
			}
			socketClient = new Socket(hostname, port);
			System.out.println("Connection started");
			creatingcommunication();
			System.out.println(response);
		} catch (IOException e) {
			System.out.println("Errors while connecting");
			throw new IOException("Cannot connect to " + hostname + ":" + port);
		}
		in = new Scanner(System.in);
	}

	public void creatingcommunication() throws IOException {
		// Sending information to the server
		out = new PrintWriter(socketClient.getOutputStream(), true);
		// Receiving information from the server
		bufferReader = new BufferedReader(new InputStreamReader(
				socketClient.getInputStream()));
	}

	public void send(String text) {
		out.println(text);
	}

	public String receive() throws IOException {
		return bufferReader.readLine();
	}
}
